
#include "copyright.h"
#include "synch.h"
#include "system.h"
#include <iostream>

Thread *ticketTakerThreads[5];

enum ClerkStateEnum ticketTakerStates[5];

/*int ticketTakerConditionVariables[5];
int ticketTakerLineConditionVariables[5];
int ticketTakerLocks[5];*/

Condition *ticketTakerConditionVariables[5];
Condition *ticketTakerLineConditionVariables[5];
Lock *ticketTakerLocks[5];
int ticketTakerLineCount[5];

/*int ticketTakerLineLock;
int totalTicketLock;
int takingTicketsLock;
int ticketTakerLineCount[5];*/

Lock *ticketTakerLineLock;
Lock *totalTicketLock;
Lock *takingTicketsLock;

bool dontGoIn[5];

int numberOfTickets[5];



void TicketTaker(int TakerNumber)
{
	while(true)
	{
onBreak:
		if(ticketTakerStates[TakerNumber]==on_break)
		{
			printf("%s %i going on break\n",currentThread->getName(),TakerNumber);
		}
		
		
		ticketTakerLineLock->Acquire();		//Lock the lines
		ticketTakerLocks[TakerNumber]->Acquire();
		
		/*LockAcquire(ticketTakerLineLock);
		LockAcquire(ticketTakeLocks[TakerNumber]);*/
		
		dontGoIn[TakerNumber]=true;
		

		/*for(int i=0; ticketTakerStates[TakerNumber]==on_break; i++)
		{
			currentThread->Yield();
			if(i==BREAK_LENGTH)
			{
				printf("%s %i coming off of break\n",currentThread->getName(),TakerNumber);
				ticketTakerStates[TakerNumber]=available;
				break;
			}
		}*/
		
		if(ticketTakerStates[TakerNumber]!=on_break)
		{
			
			
			if(ticketTakerLineCount[TakerNumber]>0)	//If there is a line
			{
				printf("%s %i has a line length %i and is signaling a customer\n",currentThread->getName(),TakerNumber,ticketTakerLineCount[TakerNumber]);
				
				ticketTakerLineConditionVariables[TakerNumber]->Signal(ticketTakerLineLock);	//Wake up the first person in line
				
				/*CVSignal(ticketTakerLineConditionVariables[TakerNumber],ticketTakerLineLock);*/
				ticketTakerLineCount[TakerNumber]--;	//decrease the line size
				ticketTakerStates[TakerNumber]=busy;	//make myself busy
			}
			else					//If there isn't a line
			{
				printf("%s %i has no line. I am available for a customer\n",currentThread->getName(),TakerNumber);
				ticketTakerStates[TakerNumber]=available;	//Set myself available

			}
			
			ticketTakerLineLock->Release();	// Unlock the lines
			
			/*LockRelease(ticketTakerLineLock);*/
		}
		
		ticketTakerConditionVariables[TakerNumber]->Wait(ticketTakerLocks[TakerNumber]);	//Wait for a customer to signal
		
		/*CVWait(ticketTakerConditionVariables[TakerNumber],ticketTakerLocks[TakerNumber]);*/
		
		

		if(ticketTakerStates[TakerNumber]==on_break)
		{
			goto onBreak;
		}
		
		takingTicketsLock->Acquire();	//Make sure the manager doesn't stop you from taking tickets half way through
		totalTicketLock->Acquire();
		
		/*LockAcquire(takingTicketsLock);
		LockAcquire(totalTicketLock);*/
		
		if((ticketsTaken+numberOfTickets[TakerNumber])>25)
		{
			exit(0);
			printf("%s %i is not allowing the group into the theater. The number of tickets taken is %i and the group size is %i\n",currentThread->getName(),TakerNumber,ticketsTaken, numberOfTickets[TakerNumber]);
		}
		else if(takingTickets) 
		{
			dontGoIn[TakerNumber]=false;
			
			ticketTakerLocks[TakerNumber]->Acquire();
			
			
			/*LockAcquire(ticketTakerLocks[TakerNumber]);*/
			
			ticketsTaken+=numberOfTickets[TakerNumber];	//Increase the total number of tickets taken
			printf("%s %i is allowing the group into the theater. The number of tickets taken is %i\n",currentThread->getName(),TakerNumber,ticketsTaken);
		}
		else
		{
			printf("%s %i is not allowing the group into the theater. The number of tickets taken is %i and the group size is %i\n",currentThread->getName(),TakerNumber,ticketsTaken, numberOfTickets[TakerNumber]);
		}
		
		takingTicketsLock->Release();
		totalTicketLock->Release();
		ticketTakerConditionVariables[TakerNumber]->Signal(ticketTakerLocks[TakerNumber]);	//Alert the customer as to their next action
		ticketTakerConditionVariables[TakerNumber]->Wait(ticketTakerLocks[TakerNumber]);
		
		/*LockRelease(takingTicketsLock);
		LockRelease(totalTicketLock);
		CVSignal(ticketTakerConditionVariables[TakerNumber],ticketTakerLocks[TakerNumber]);
		CVWait(ticketTakerConditionVariables[TakerNumber], ticketTakerLocks[TakerNumber]);*/

	}
}
